﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.IO;

namespace EverydayTips
{
    public partial class Form_mainform : Form
    {
        private Guid uid;
        private DateTime TipTime;
        private Index index;
        private ArrayList IDlist;
        private bool really_quit;
        public static Guid NULLGUID = new Guid();
        private string templateFile;
        private RichTextBoxStreamType templateType;
        public static Object indexLock = new Object();
        public static bool debug = true;
        //private bool isunlocked;
        private string md5passwd;
        private bool handleLockedStatusCheck;

        public Form_mainform()
        {
            InitializeComponent();

            #region User-defined initialization
            ShowInTaskbar = false;
            init();
            DateTime dt = DateTime.Now;
            this.label_date.Text = dt.ToString("yyyy/MM/dd HH:mm:ss");
            index = Index.fetch();
            IDlist = new ArrayList();
            really_quit = false;
            //isunlocked = false;
            handleLockedStatusCheck = true;
            md5passwd = "";
            templateFile = "";
            templateType = RichTextBoxStreamType.RichText;
            #endregion
        }
        private void init()
        {
            if (!File.Exists(@"data\\index.etp"))
            {
                if (!Directory.Exists("data"))
                {
                    Directory.CreateDirectory("data");
                }
                FileStream fs = new FileStream(@"data\\index.etp", FileMode.Create);
                fs.Close();
            }
        }
        private void button_save_Click(object sender, EventArgs e)
        {
            //Util.Log("Before saving");
            //Util.Log(Util.Index2String(index));
            lock (Form_mainform.indexLock)
            {
                if (this.richTextBox_title.Text == "" || this.richTextBox_content.Text == "")
                {
                    ShowMsg("Abort saving, the title and content is empty!");
                    return;
                }
                TipTime = DateTime.Now;
                if (uid == NULLGUID)
                    uid = Guid.NewGuid();
                else
                {
                    Tip oldTip = Tip.fetch(uid);
                    index.deleteItem(uid, oldTip.date.ToString("yyyyMMdd"), oldTip.keywords);
                }
                Tip t = new Tip(uid, this.richTextBox_title.Rtf, this.richTextBox_source.Rtf, this.richTextBox_keywords.Text, this.richTextBox_content.Rtf, TipTime);
                if (this.checkBox_lock.Checked)
                {
                    t.SetMd5Passwd(this.md5passwd);
                }
                Tip.save(t);
                index.indexItem(uid, this.richTextBox_title.Text, TipTime.ToString("yyyyMMdd"), this.richTextBox_keywords.Text);
                Index.save(index);
                ShowMsg("This item is saved successfully!");
            }
            //Util.Log("After saving");
           // Util.Log(Util.Index2String(index));
        }

        private void button_showByKeywords_Click(object sender, EventArgs e)
        {
            IDlist = index.getIDlistByKeywords(this.richTextBox_filter_keywords.Text);
            dofetchItem();
            this.listBox_title.Focus();
        }
        private void button_showbyDate_Click(object sender, EventArgs e)
        {
            string date = this.dateTimePicker_filter_date.Value.ToString("yyyyMMdd");
            IDlist = index.getIDlistByDate(date);
            dofetchItem();
            this.listBox_title.Focus();
        }
        private void resetFields()
        {
            uid = NULLGUID;
            this.richTextBox_title.Text = "";
            this.richTextBox_source.Text = "";
            this.richTextBox_keywords.Text = "";
            this.richTextBox_content.Text = "";
            this.checkBox_lock.Checked = false;
            this.richTextBox_filter_keywords.Text = "";
            this.label_iterator.Text = "0/0";
            this.label_date.Text = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
            this.dateTimePicker_filter_date.Value = DateTime.Now;
            this.listBox_title.Items.Clear();
            this.IDlist.Clear();
        }
        private void dofetchItem()
        {
            if (IDlist != null && IDlist.Count != 0)
            {
                listBox_title.Items.Clear();
                foreach (Guid uid in IDlist)
                {
                    this.listBox_title.Items.Add(index.Tiplist[uid]);
                }
                if (listBox_title.Items.Count > 0)
                    listBox_title.SelectedIndex = 0;
                fetchOneItem();
            }
            else
            {
                resetFields();
                ShowMsg("No matched Items!");
            }
        }

        private void fetchOneItem()
        {
            handleLockedStatusCheck = false;
            if (IDlist == null || IDlist.Count <= 0 || listBox_title.SelectedIndex == -1)
            {
                resetFields();
                ShowMsg("No more Tips!");
                return;
            }

            uid = (Guid)IDlist[listBox_title.SelectedIndex % IDlist.Count];
            Tip t = Tip.fetch(uid);
            
            this.checkBox_lock.Checked = t.locked;
            this.md5passwd = t.getMd5Passwd();
            if (t.locked && (!unlockItem()))
            {
                this.label_date.Text = t.date.ToString("yyyy/MM/dd HH:mm:ss");

                this.richTextBox_title.Text = "Protected!";
                this.richTextBox_source.Text = "Protected!";
                this.richTextBox_keywords.Text = "Protected!";
                this.richTextBox_content.Text = "This item is protected, Please input the password to unlock it first!";
                
                ShowMsg("Input password to unlock this item.");
                //this.textBox_passwd.Focus();
            }
            else
            {
                this.richTextBox_title.Rtf = t.title;
                this.richTextBox_source.Rtf = t.source;
                this.richTextBox_keywords.Text = t.keywords;
                this.richTextBox_content.Rtf = t.content;
                this.TipTime = t.date;
                this.checkBox_lock.Checked= t.locked;
                this.label_date.Text = t.date.ToString("yyyy/MM/dd HH:mm:ss");
                this.label_iterator.Text = (listBox_title.SelectedIndex + 1) + "/" + IDlist.Count;
                ShowMsg("Showing Tip ..."); 
            }
            this.listBox_title.Focus();
            handleLockedStatusCheck = true;
            
        }

        private void loadTemplate()
        {
            if(templateFile!="")
                this.richTextBox_content.LoadFile(templateFile, templateType);
        }
        private void button_new_Click(object sender, EventArgs e)
        {
            resetFields();
            loadTemplate();
            ShowMsg("You are writing a new Tip!");
        }

        private void button_next_Click(object sender, EventArgs e)
        {
            if (listBox_title.Items.Count > 0)
            {
                listBox_title.SelectedIndex = (listBox_title.SelectedIndex + 1) % listBox_title.Items.Count;
                fetchOneItem();
            }
        }

        private void richTextBox_filter_keywords_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == '\r')
            {
                IDlist = index.getIDlistByKeywords(this.richTextBox_filter_keywords.Text);
                dofetchItem();
                this.listBox_title.Focus();
            }
        }

        private void dateTimePicker_filter_date_CloseUp(object sender, EventArgs e)
        {
            string date = this.dateTimePicker_filter_date.Value.ToString("yyyyMMdd");
            IDlist = index.getIDlistByDate(date);
            dofetchItem();
            this.listBox_title.Focus();
        }

        private void button_reset_Click(object sender, EventArgs e)
        {
            resetFields();
            ShowMsg("The fields are reset!");
        }
        private void copyFromRichTextBox(RichTextBox from)
        {
            from.SelectAll();
            from.Copy();
            from.DeselectAll();
            richTextBox_hidden2.Paste();
        }
        private void copyFromString(string msg)
        {
            richTextBox_hidden1.Clear();
            richTextBox_hidden1.Text = msg;
            richTextBox_hidden1.SelectAll();
            richTextBox_hidden1.Copy();
            richTextBox_hidden1.DeselectAll();
            richTextBox_hidden2.Paste();
        }
        private void button_export_Click(object sender, EventArgs e)
        {
            richTextBox_hidden2.Clear();
            copyFromString("###########################################\r\nTitle: ");
            copyFromRichTextBox(richTextBox_title);
            copyFromString("\r\nSource: ");
            copyFromRichTextBox(richTextBox_source);
            copyFromString("\r\nKeywords: ");
            copyFromRichTextBox(richTextBox_keywords);
            copyFromString("\r\n###########################################\r\n");
            copyFromRichTextBox(richTextBox_content);

            string text = "###########################################\r\n";
            text +=       "Title: "+this.richTextBox_title.Text+"\r\n";
            text +=       "Source: " + this.richTextBox_source.Text + "\r\n";
            text += "Keywords: " + this.richTextBox_keywords.Text + "\r\n";
            text += "###########################################\r\n";
            text += this.richTextBox_content.Text;
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();
            saveFileDialog1.Filter = "Rich Text Format|*.rtf|Plain Text|*.txt";
            saveFileDialog1.Title = "Save an Tip File";
            saveFileDialog1.ShowDialog();

            // If the file name is not an empty string open it for saving.
            if (saveFileDialog1.FileName != "")
            {
                // Saves the Image via a FileStream created by the OpenFile method.
                System.IO.FileStream fs =
                   (System.IO.FileStream)saveFileDialog1.OpenFile();
                // Saves the Image in the appropriate ImageFormat based upon the
                // File type selected in the dialog box.
                // NOTE that the FilterIndex property is one-based.
                switch (saveFileDialog1.FilterIndex)
                {
                    case 1:
                        richTextBox_hidden2.SaveFile(fs, RichTextBoxStreamType.RichText);
                        break;
                    case 2:
                        byte[] msg = new UTF8Encoding(true).GetBytes(text);
                        fs.Write(msg, 0, msg.Length);
                        break;

                }

                fs.Close();
            }
            ShowMsg("The Tip is exported to: " + saveFileDialog1.FileName);

        }
        private RichTextBox getFocusedControl()
        {
            if (this.richTextBox_title.Focused)
                return this.richTextBox_title;
            if (this.richTextBox_source.Focused)
                return this.richTextBox_source;
            if (this.richTextBox_keywords.Focused)
                return this.richTextBox_keywords;
            if (this.richTextBox_content.Focused)
                return this.richTextBox_content;
            return null;
        }
        private void toolStripMenuItem_bold_Click(object sender, EventArgs e)
        {
            getFocusedControl().SelectionFont = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
        }

        private void redToolStripMenuItem_color_Click(object sender, EventArgs e)
        {
            ColorDialog MyDialog = new ColorDialog();
            // Keeps the user from selecting a custom color.
            MyDialog.AllowFullOpen = false;
            // Sets the initial color select to the current text color.
            MyDialog.Color = getFocusedControl().SelectionColor;

            // Update the text box color if the user clicks OK 
            if (MyDialog.ShowDialog() == DialogResult.OK)
                getFocusedControl().SelectionColor = MyDialog.Color;

        }

        private void fontToolStripMenuItem_font_Click(object sender, EventArgs e)
        {
            FontDialog fontDialog1 = new FontDialog();
            fontDialog1.ShowColor = true;

            fontDialog1.Font = getFocusedControl().SelectionFont;
            fontDialog1.Color = getFocusedControl().SelectionColor;

            if (fontDialog1.ShowDialog() != DialogResult.Cancel)
            {
                getFocusedControl().SelectionFont = fontDialog1.Font;
                getFocusedControl().SelectionColor = fontDialog1.Color;
            }

        }

        private void button_showall_Click(object sender, EventArgs e)
        {
            this.IDlist = index.getIDlist();
            dofetchItem();
        }

        private void button_delete_Click(object sender, EventArgs e)
        {
            if (uid != NULLGUID)
            {
                if (this.checkBox_lock.Checked)
                {
                    if (!unlockItem())
                    {
                        ShowMsg("Please unlock this item before deleting it!");
                        return;
                    }
                }
                Tip.delete(uid);
                index.deleteItem(uid,TipTime.ToString("yyyyMMdd"), this.richTextBox_keywords.Text);
                if (listBox_title.Items.Count > 0)
                {
                    int oldindex = listBox_title.SelectedIndex;
                    if(oldindex < listBox_title.Items.Count)
                        listBox_title.Items.RemoveAt(oldindex);
                    if(oldindex < IDlist.Count)
                        IDlist.RemoveAt(oldindex);
                    if (listBox_title.Items.Count > 0)
                    {
                        listBox_title.SelectedIndex = oldindex % listBox_title.Items.Count;
                        fetchOneItem();
                    }
                    else
                    {
                        resetFields();
                    }
                } 
                ShowMsg("The item is deleted successfully!");
            }
            else
            {
                ShowMsg("No stored Tip is selected! You haven't saved it yet?");
            }
            
        }

        private void ShowMsg(string msg)
        {
            this.label_msg.Text = msg;
        }

        private void button_debug_Click(object sender, EventArgs e)
        {
            
           
        }

        private void copyToolStripMenuItem_copy_Click(object sender, EventArgs e)
        {
            getFocusedControl().Copy();
        }

        private void cutToolStripMenuItem_cut_Click(object sender, EventArgs e)
        {
            getFocusedControl().Cut();
        }

        private void pasteToolStripMenuItem_paste_Click(object sender, EventArgs e)
        {
            getFocusedControl().Paste();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            really_quit = true;
            this.Close();
        }
        private void Form_mainform_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!really_quit)
            {
                e.Cancel = true;
                this.Visible = false;
            }
        }

        private void Form_mainform_FormClosed(object sender, FormClosedEventArgs e)
        {
            Index.save(index);
        }

        private void notifyIcon_notifier_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.checkBox_ontop.Checked = true;
            this.ShowInTaskbar = false;
            this.WindowState = FormWindowState.Normal;
            this.Visible = true;
        }

        private void showToolStripMenuItem_show_Click(object sender, EventArgs e)
        {
            this.checkBox_ontop.Checked = true;
            this.Visible = true;
        }

        private void hideToolStripMenuItem_hide_Click(object sender, EventArgs e)
        {
            this.Visible = false;
        }

        private void Form_mainform_DragDrop(object sender, DragEventArgs e)
        {
            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
            if (files.Length == 1)
            {
                richTextBox_source.Text = files[0];
            }
            else
            {
                string source = "";
                foreach (string file in files)
                {
                    source += file;
                    source += ";";
                }
                richTextBox_source.Text = source;
            }
        }

        private void Form_mainform_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop, false) == true)
                e.Effect = DragDropEffects.All;
        }

        private void listBox_title_SelectedIndexChanged(object sender, EventArgs e)
        {
            if(listBox_title.SelectedIndex != -1)
                fetchOneItem();
        }

        private void reddenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            getFocusedControl().SelectionColor = Color.Red;
        }

        private void button_back_Click(object sender, EventArgs e)
        {
            if (listBox_title.Items.Count > 0)
            {
                listBox_title.SelectedIndex = (listBox_title.SelectedIndex + listBox_title.Items.Count - 1) % listBox_title.Items.Count;
                fetchOneItem();
            }
        }

        private void button_template_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            openFileDialog1.InitialDirectory = System.AppDomain.CurrentDomain.BaseDirectory.ToString()+"data";
            openFileDialog1.Filter = "Rich Text Files|*.rtf|Text Files|*.txt";
            openFileDialog1.FilterIndex = 1;
            openFileDialog1.RestoreDirectory = true;

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                this.label_template.Text = "Template: " + openFileDialog1.SafeFileName;
                switch (openFileDialog1.FilterIndex)
                {
                    case 1:
                        templateFile = openFileDialog1.FileName;
                        templateType = RichTextBoxStreamType.RichText;
                        richTextBox_content.LoadFile(openFileDialog1.FileName, RichTextBoxStreamType.RichText);
                        break;
                    case 2:
                        templateFile = openFileDialog1.FileName;
                        templateType = RichTextBoxStreamType.PlainText;
                        richTextBox_content.LoadFile(openFileDialog1.FileName, RichTextBoxStreamType.PlainText);
                        break;

                }
            }

        }

        private void checkBox_ontop_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox_ontop.Checked)
            {
                this.TopMost = true;
            }
            else
            {
                this.TopMost = false;
            }
        }

        private void checkBox_problem_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox_problem.Checked)
            {
                this.button_reindex.Visible = true;
                debug = true;
            }
            else
            {
                this.button_reindex.Visible = false;
                debug = false;
            }
            
        }
        private void button_reindex_Click(object sender, EventArgs e)
        {
            ArrayList tiplist = index.getIDlist();
            index.keywordsIndex.Clear();
            for (int i = 0; i < tiplist.Count; i++)
            {
                Guid uid = (Guid) tiplist[i];    
                Tip t = Tip.fetch(uid);
                index.addKeywordsIndex(t.keywords, uid);
            }
            ShowMsg("Rebulid index successfully!");
        }
        private bool unlockItem()
        {
            if (Util.getMd5Hash(this.textBox_passwd.Text) == md5passwd)
            {
                ShowMsg("The item is unloced successfully!");
                return true;
                
            }
            else
            {
                ShowMsg("The password is invalid!");
                return false;
            }
        }
        private void button_unlock_Click(object sender, EventArgs e)
        {
            //unlockItem();
            fetchOneItem();
        }

        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == '\r')
            {
                fetchOneItem();
            }
        }

        private void checkBox_lock_CheckedChanged(object sender, EventArgs e)
        {
            if (handleLockedStatusCheck)
            {
                if (this.checkBox_lock.Checked)
                {
                    if (this.textBox_setpass.Text != "" && this.textBox_setpass.Text != "Set Password ...")
                    {
                        this.md5passwd = Util.getMd5Hash(this.textBox_setpass.Text);
                        ShowMsg("The password is successfully set!");
                        this.textBox_setpass.Text = "Set Password ...";
                    }
                    else
                    {
                        this.checkBox_lock.Checked = false;
                        ShowMsg("Please set a password to lock this item!");
                        this.textBox_setpass.Text = "Set Password ...";
                    }
                }
            }

        }

        private void textBox_setpass_Click(object sender, EventArgs e)
        {
            this.textBox_setpass.Text = "";
        }
    }
}
